#include <vector>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <functional>
#include <unistd.h>
#include <cstdint>

using TaskCallback = std::function<void()>;
using CleanCallback = std::function<void()>;

class TaskClock
{
public:
    TaskClock(uint64_t id, uint32_t interval,TaskCallback tc)
    :_id(id),
    _interval(interval),
    _tc(tc),
    _switch(true)
    {}

    //返回间隔时间
    uint32_t getInterval()
    {
        return _interval;
    }

    //设置清理函数
    void setCleanCallback(CleanCallback cc)
    {
        _cc = cc;
    }

    //关闭时钟
    void shutTaskClock()
    {
        _switch = false;
    }

    //释放
    ~TaskClock()
    {
        if(true == _switch)
        {
            _tc();
        }

        _cc();
    }
private:
    uint64_t _id; // 时钟id
    uint32_t _interval; //间隔时间
    bool _switch; //是否执行函数
    TaskCallback _tc;   //时间到了，触发的函数
    CleanCallback _cc;  //删除时钟对象的函数
};

class TimeWheel
{
    using WeatPtr = std::weak_ptr<TaskClock>;
    using TaskPtr = std::shared_ptr<TaskClock>;
public:
    TimeWheel(int cap)
    :_tick(0),
    _cap(cap),
    _tasks(_cap)
    {}

    void timeAdd(uint64_t id, uint32_t interval,TaskCallback tc)
    {
        TaskPtr taskptr = std::make_shared<TaskClock>(id,interval,tc);
        taskptr->setCleanCallback(std::bind(&TimeWheel::Remove,this,id));
        int pos = (interval + _tick) % _cap;
        _tasks[pos].push_back(taskptr);
        _id_task[id] = WeatPtr(taskptr);
    }

    void refreshTask(uint64_t id)
    {
        auto it = _id_task.find(id);
        if(nullptr == it)
        {
            return;
        }

        TaskPtr taskptr(it->second);
        int pos = (taskptr->getInterval() + _tick) % _cap;
        _tasks[pos].push_back(taskptr);
    }

    void shutTaskClock(uint64_t id)
    {
        auto it = _id_task.find(id);
        if(nullptr == it)
        {
            return;
        }

        TaskPtr taskptr(it->second);
        taskptr->shutTaskClock();
    }

    void run()
    {
        _tick = (_tick + 1) % _cap;
        _tasks[_tick].clear();
    }

    ~TimeWheel()
    {}
private:
    void Remove(uint64_t id)
    {
        auto it = _id_task.find(id);
        if(nullptr == it)
        {
            return;
        }

        _id_task.erase(it);
    }

private:
    int _tick;
    int _cap;
    std::vector<std::vector<TaskPtr>> _tasks;
    std::unordered_map<uint64_t,WeatPtr> _id_task;
};

class Test {
    public:
        Test() {std::cout << "构造" << std::endl;}
        ~Test() {std::cout << "析构" << std::endl;}
};

void DelTest(Test *t) {
    delete t;
}

void test_time_wheel()
{
    TimeWheel tw(60);

    Test *t = new Test();

    tw.timeAdd(888, 5, std::bind(DelTest, t));

    for(int i = 0; i < 5; i++) {
        sleep(1);
        tw.refreshTask(888);
        tw.run();
        std::cout << "刷新了一下定时任务，重新需要5s中后才会销毁\n";
    }
    tw.shutTaskClock(888);
    while(1) {
        sleep(1);
        std::cout << "-------------------\n";
        tw.run();//向后移动秒针
    }
}


